<?php
/**
 * Created by laoyu.
 * User: hilaoyu@qq.com
 * Date: 2018/4/27
 * Time: 15:42
 */

namespace Hilaoyu\LaravelExtend\Services\Captcha;

use Hilaoyu\LaravelExtend\Supports\Uuid;
use Hilaoyu\Utils\Traits\ErrorsTrait;
use Hilaoyu\Utils\UtilRegex;
use Hilaoyu\Utils\UtilStr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Mail;
use Gregwar\Captcha\CaptchaBuilder;

class CaptchaService
{
    use ErrorsTrait;
    protected $_cache_tags='laravel-extend:captcha';
    /**
     * @param $code
     * @param string $send_to
     * @return array
     */

    protected function getCodeLength($code_type = "")
    {
        if ("image" == $code_type) {
            $len = config('captcha.code_length_image', 4);
        } elseif ("mobile" == $code_type) {
            $len = config('captcha.code_length_mobile', 6);
        } elseif ("email" == $code_type) {
            $len = config('captcha.code_length_email', 6);
        } else {
            $len = config('captcha.code_length', 6);
        }

        return min($len, 10);
    }
    protected function getCodeChars(){
        return  config('captcha.chars','abcdefghijklmnpqrstuvwxyz123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ');
    }

    protected function captchaSave($code,$send_to = '',$expire_seconds=600){
        $code_id = Uuid::generate();
        if(!Cache::put($this->buildSaveKey($code_id),[
            'code_id'=>$code_id,
            'code'=>$code,
            'send_to'=>$send_to,
        ],Carbon::now()->addSeconds(intval($expire_seconds)))){
            $this->setError('保存验证码失败');
            return null;
        }

        return $code_id;
    }
    protected function captchaGet($code_id){
        return Cache::get($this->buildSaveKey($code_id),null);

    }
    protected function captchaDelete($code_id){
        return Cache::forget($this->buildSaveKey($code_id));

    }
    protected function buildSaveKey($code_id){
        $code_id = trim($code_id);
        return 'laravel-extend:captcha:'.$code_id;
    }

    public function verify($code_id,$code,$send_to = null,$force_delete = false){
        $code_id = trim($code_id);
        if(!$code_id){
            return false;
        }

        $captcha = $this->captchaGet($code_id);
        if(!$captcha){
            return false;
        }

        if(UtilStr::lower($code) != UtilStr::lower(data_get($captcha,'code'))){
            if ($force_delete){
                $this->captchaDelete($code_id);
            }
            return false;
        }

        if($send_to && UtilStr::lower($send_to) != UtilStr::lower(data_get($captcha,'send_to'))){
            if ($force_delete){
                $this->captchaDelete($code_id);
            }
            return false;
        }

        $this->captchaDelete($code_id);

        return true;
    }

    public function generateImg($width = 150, $height = 40){
        $width = intval($width);
        $width = max(min($width,300),75);
        $height = intval($height);
        $height = max(min($height,80),20);


        $builder = new CaptchaBuilder(UtilStr::randString($this->getCodeLength("image"),$this->getCodeChars()));
        $builder->build($width,$height);
        $code_data = $builder->inline();
        $code = $builder->getPhrase();

        if(empty($code_data) || empty($code)){
            $this->SetError('生成图片验证码失败');
            return false;
        }

        $code_id = $this->captchaSave($code,'image',config('captcha.expire_seconds_image',600));

        if(!$code_id){
            return false;
        }

        return ['code_id'=>$code_id,'code'=>$code_data];

    }

    public function generateEmail($send_to,$template=''){
        $send_to = trim($send_to);
        $template = trim($template);

        if(!filter_var($send_to, FILTER_VALIDATE_EMAIL))
        {
            $this->SetError('接收邮箱格式错误');
            return false;
        }
        $code = UtilStr::randString($this->getCodeLength("email"),$this->getCodeChars());

        if(!$template || !($tpl = config('mail.tpls.'.$template))){
            $tpl = '您的验证码为:#code#';
        }
        $body = UtilStr::replace($tpl,['#code#'=>$code]);

        $subject = config('app.name') . '验证码';

        if(config('mail.testing')){
            comResponse()->withDebug($code,'captcha_code_val');
        }else{
            try{
                Mail::raw($body,function ($mail)use ($send_to,$subject){
                    $mail->to($send_to)->subject($subject);
                    //dd($mail);
                });
            }catch (\Exception $exception){
                $this->SetError($exception->getMessage());
                return false;
            }
        }



        return $this->captchaSave($code,$send_to,config('captcha.expire_seconds_email',600));

    }

    public function generateMobile($send_to,$template=''){
        $send_to = trim($send_to);
        $template = trim($template);
        if(!$template || !config('sms.config.tpls.'.$template)){
            $template = 'captcha';
        }

        if(!UtilRegex::isMobile($send_to))
        {
            $this->SetError('接收手机号格式错误');
            return false;
        }
        $code = UtilStr::randString($this->getCodeLength("mobile"),'0123456789');

        if(config('sms.testing')){
            $code = '1234';
            comResponse()->withDebug($code,'captcha_code_val');
        }else{

            $send_status =  app('sms')->send($send_to,['#code#'=>$code],config('sms.config.tpls.'.$template));

            if(true !== $send_status){
                $this->SetError(app('sms')->getError());
                return false;
            }
        }

        return $this->captchaSave($code,$send_to,config('captcha.expire_seconds_mobile',600));

    }



    public function captchaCacheClear(){
        //return Cache::tags($this->_cache_tags)->flush();

    }

}
